package com.mrper.asm

import com.android.build.api.instrumentation.AsmClassVisitorFactory
import com.android.build.api.instrumentation.ClassContext
import com.android.build.api.instrumentation.ClassData
import com.android.build.api.instrumentation.FramesComputationMode
import com.android.build.api.instrumentation.InstrumentationParameters
import com.android.build.api.instrumentation.InstrumentationScope
import com.android.build.api.variant.AndroidComponentsExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.util.TraceClassVisitor
import java.io.File
import java.io.PrintWriter

class AsmPlugin : Plugin<Project> {

    override fun apply(target: Project) {
        println("================== AsmPlugin is Running =================")
        val extension = target.extensions.create("AsmConfig", AsmConfig::class.java)
        val androidComponents = target.extensions
            .getByType(AndroidComponentsExtension::class.java)
        androidComponents.onVariants { variant ->
            variant.instrumentation.transformClassesWith(
                ViewOnClickClassVisitorFactory::class.java,
                InstrumentationScope.ALL) { it.enabled.set(extension.enabled) }
            variant.instrumentation.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES)
        }
    }

    interface ViewOnClickParams : InstrumentationParameters {

        @get:Input
        val enabled: Property<Boolean>

    }

    abstract class ViewOnClickClassVisitorFactory : AsmClassVisitorFactory<ViewOnClickParams> {

        override fun createClassVisitor(
            classContext: ClassContext,
            nextClassVisitor: ClassVisitor
        ): ClassVisitor {
            return if (parameters.get().enabled.get()) {
                GlobalClassVisitor(Opcodes.ASM9, nextClassVisitor)
            } else {
                TraceClassVisitor(nextClassVisitor, PrintWriter(File("trace_out")))
            }
        }

        override fun isInstrumentable(classData: ClassData): Boolean = true
        // classData.className.startsWith("com.mrper.analysis")

    }

}